package org.huzhp.gateway.exception;

import org.huzhp.gateway.service.AbstractAuditLogService;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.reactive.function.server.*;

import java.util.Map;

/**
 * @Description: 网关通用返回格式
 * @Author: huzp
 * @CreateDate: 2020/3/13 9:41
 * @Version: 1.0
 */
public class GatewayJsonWebErrorExceptionHandler extends DefaultErrorWebExceptionHandler {

    private AbstractAuditLogService auditLogService;

    public GatewayJsonWebErrorExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
        // 这里其实可以根据异常类型进行定制化逻辑
        Map<String, Object> error = super.getErrorAttributes(request, includeStackTrace);
        ServerHttpRequest httpRequest = request.exchange().getRequest();
//        Route route = request.exchange().getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
//        error.put("routeId", route.getId());
        Long startTime = request.exchange().getAttribute("startTime");
        Long executeTime = null;
        if (startTime != null) {
            executeTime = (System.currentTimeMillis() - startTime);
        }
        error.put("executeTime", executeTime);

        auditLogService.logError(error, httpRequest);
        return error;
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    public void setAuditLogService(AbstractAuditLogService auditLogService) {
        this.auditLogService = auditLogService;
    }
}
